import time
import machine
from machine import Pin
from time import sleep_ms, sleep_us


class TFT():
    def __init__(self, sda, clk, dc, rst=None, cs=None, blk=None, USE_HORIZONTAL=0):
        self.USE_HORIZONTAL = USE_HORIZONTAL
        self.sda = machine.Pin(sda, Pin.OUT)
        self.clk = machine.Pin(clk, Pin.OUT)
        self.dc = machine.Pin(dc, Pin.OUT)
        if rst:
            self.rst = machine.Pin(rst, Pin.OUT)
        if cs:
            self.cs = machine.Pin(cs, Pin.OUT)
        if blk:
            self.blk = machine.Pin(blk, Pin.OUT)

    def LCD_Writ_Bus(self, dat):
        for i in range(8):
            self.clk.value(0)
            sleep_us(10)
            if dat & 0x00000080 != 0:
                self.sda.value(1)
            else:
                self.sda.value(0)
            sleep_us(10)
            self.clk.value(1)
            dat <<= 1
            sleep_us(10)

    def LCD_WR_DATA8(self, u8_dat):
        self.LCD_Writ_Bus(u8_dat)

    def LCD_WR_DATA(self, u16_dat):
        self.LCD_Writ_Bus(u16_dat >> 8)
        self.LCD_Writ_Bus(u16_dat)

    def LCD_WR_REG(self, u8_dat):
        self.dc.value(0)
        sleep_us(10)
        self.LCD_Writ_Bus(u8_dat)
        self.dc.value(1)
        sleep_us(10)

    def init(self):
        # 卖家提供的初始化代码
        print('lcd init processing')
        if hasattr(self, 'cs'):
            self.cs.value(0)
        sleep_ms(100)
        if hasattr(self, 'rst'):
            self.rst.value(0)
        sleep_ms(100)
        if hasattr(self, 'rst'):
            self.rst.value(1)
        sleep_ms(100)
        if hasattr(self, 'blk'):
            self.blk.value(1)
        sleep_ms(100)

        # ** ** ** ** ** ** *Start Initial Sequence ** ** ** ** ** #
        self.LCD_WR_REG(0x11)  # Sleep out
        sleep_ms(120)  # Delay 120 ms
        # ** ** ** ** ** ** *Start Initial Sequence ** ** ** ** ** #
        self.LCD_WR_REG(0x36)
        if self.USE_HORIZONTAL == 0:
            self.LCD_WR_DATA8(0x00)
        elif self.USE_HORIZONTAL == 1:
            self.LCD_WR_DATA8(0xC0)
        elif self.USE_HORIZONTAL == 2:
            self.LCD_WR_DATA8(0x70)
        else:
            self.LCD_WR_DATA8(0xA0)

        self.LCD_WR_REG(0x3A)
        self.LCD_WR_DATA8(0x06)

        self.LCD_WR_REG(0xB2)
        self.LCD_WR_DATA8(0x1f)
        self.LCD_WR_DATA8(0x1f)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x33)
        self.LCD_WR_DATA8(0x33)

        self.LCD_WR_REG(0xB7)
        self.LCD_WR_DATA8(0x12)

        self.LCD_WR_REG(0xBB)
        self.LCD_WR_DATA8(0x35)

        self.LCD_WR_REG(0xC0)
        self.LCD_WR_DATA8(0x2C)

        self.LCD_WR_REG(0xC2)
        self.LCD_WR_DATA8(0x01)

        self.LCD_WR_REG(0xC3)
        self.LCD_WR_DATA8(0x15)

        self.LCD_WR_REG(0xC4)
        self.LCD_WR_DATA8(0x20)

        self.LCD_WR_REG(0xC6)
        self.LCD_WR_DATA8(0x13)

        self.LCD_WR_REG(0xD0)
        self.LCD_WR_DATA8(0xA4)
        self.LCD_WR_DATA8(0xA1)

        self.LCD_WR_REG(0xD6)
        self.LCD_WR_DATA8(0xA1)

        self.LCD_WR_REG(0xE0)
        self.LCD_WR_DATA8(0xF0)
        self.LCD_WR_DATA8(0x06)
        self.LCD_WR_DATA8(0x0D)
        self.LCD_WR_DATA8(0x0B)
        self.LCD_WR_DATA8(0x0A)
        self.LCD_WR_DATA8(0x07)
        self.LCD_WR_DATA8(0x2E)
        self.LCD_WR_DATA8(0x43)
        self.LCD_WR_DATA8(0x45)
        self.LCD_WR_DATA8(0x38)
        self.LCD_WR_DATA8(0x14)
        self.LCD_WR_DATA8(0x13)
        self.LCD_WR_DATA8(0x25)
        self.LCD_WR_DATA8(0x29)

        self.LCD_WR_REG(0xE1)
        self.LCD_WR_DATA8(0xF0)
        self.LCD_WR_DATA8(0x07)
        self.LCD_WR_DATA8(0x0A)
        self.LCD_WR_DATA8(0x08)
        self.LCD_WR_DATA8(0x07)
        self.LCD_WR_DATA8(0x23)
        self.LCD_WR_DATA8(0x2E)
        self.LCD_WR_DATA8(0x33)
        self.LCD_WR_DATA8(0x44)
        self.LCD_WR_DATA8(0x3A)
        self.LCD_WR_DATA8(0x16)
        self.LCD_WR_DATA8(0x17)
        self.LCD_WR_DATA8(0x26)
        self.LCD_WR_DATA8(0x2C)

        self.LCD_WR_REG(0xE4)
        self.LCD_WR_DATA8(0x1D)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x00)

        self.LCD_WR_REG(0x21)

        self.LCD_WR_REG(0x29)

        self.LCD_WR_REG(0x2A)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0xEF)

        self.LCD_WR_REG(0x2B)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0x00)
        self.LCD_WR_DATA8(0xEF)
        print('lcd init end')

    def LCD_Fill(self, xsta, ysta, xend, yend, color):
        self.LCD_Address_Set(xsta, ysta, xend - 1, yend - 1)  # 设置显示范围
        for i in range(ysta, yend):
            for i in range(xsta, xend):
                self.LCD_WR_DATA(color)

    def LCD_Address_Set(self, x1, y1, x2, y2):
        if (self.USE_HORIZONTAL == 0):
            self.LCD_WR_REG(0x2a)  # 列地址设置
            self.LCD_WR_DATA(x1)
            self.LCD_WR_DATA(x2)
            self.LCD_WR_REG(0x2b)  # 行地址设置
            self.LCD_WR_DATA(y1)
            self.LCD_WR_DATA(y2)
            self.LCD_WR_REG(0x2c)  # 储存器写

        elif (self.USE_HORIZONTAL == 1):

            self.LCD_WR_REG(0x2a)  # 列地址设置
            self.LCD_WR_DATA(x1)
            self.LCD_WR_DATA(x2)
            self.LCD_WR_REG(0x2b)  # 行地址设置
            self.LCD_WR_DATA(y1 + 80)
            self.LCD_WR_DATA(y2 + 80)
            self.LCD_WR_REG(0x2c)  # 储存器写
        elif (self.USE_HORIZONTAL == 2):
            self.LCD_WR_REG(0x2a)  # 列地址设置
            self.LCD_WR_DATA(x1)
            self.LCD_WR_DATA(x2)
            self.LCD_WR_REG(0x2b)  # 行地址设置
            self.LCD_WR_DATA(y1)
            self.LCD_WR_DATA(y2)
            self.LCD_WR_REG(0x2c)  # 储存器写
        else:
            self.LCD_WR_REG(0x2a)  # 列地址设置
            self.LCD_WR_DATA(x1 + 80)
            self.LCD_WR_DATA(x2 + 80)
            self.LCD_WR_REG(0x2b)  # 行地址设置
            self.LCD_WR_DATA(y1)
            self.LCD_WR_DATA(y2)
            self.LCD_WR_REG(0x2c)  # 储存器写
